package com.wjw.java.thread;

public class Synchronized_2 {
    public static void main(String[] args) {

        //使用继承Thread类,创建了三个不同的线程类
        SellTicketSafe2 t1 = new SellTicketSafe2();
        t1.setName("窗口A:");
        SellTicketSafe2 t2 = new SellTicketSafe2();
        t2.setName("窗口B:");
        SellTicketSafe2 t3 = new SellTicketSafe2();
        t3.setName("窗口C:");
        //此时t1、t2、t3线程的this都是他们自己,而非同一个对象
        //锁this,此时的this为t1、t2、t3自己,非同一对象,不能保证线程安全
        //锁同一个其他对象,此时同一对象lock为t1、t2、t3各自自己的lock,非同一lock,,不能保证线程安全
        //锁类名.class都能保证线程安全
        t1.start();
        t2.start();
        t3.start();
    }
}

//实现继承Thread类
class SellTicketSafe2 extends Thread{
    //使用static修饰,共享数据
    private static int ticketNum = 99;
    //是否循环
    private static boolean ifLoop = true;

    //同步方法：锁可以是this,也可以是其他对象(要求是同一个对象)
    private Object lock = new Object();

    @Override
    public void run() {
        while (ifLoop){
            //sell();//同步代码块：锁为this,不能保证线程安全
            //sell2();//同步代码块：锁为同一其他对象,不能保证线程安全
            //sell3();//同步方法：锁为this,不能保证线程安全
            //sell4();//静态同步方法：锁为类名.class 即：SellTicketSafe.class,线程安全
            sell5();//静态同步方法：锁为类名.class 即：SellTicketSafe.class,线程安全
        }
    }

    //1.使用同步代码块：锁为this
    public void sell(){
        synchronized (this){
            if(ticketNum <= 0){
                System.out.println("没票了,停止售票...");
                ifLoop = false;
                return;
            }
            String name = Thread.currentThread().getName();
            try {
                Thread.sleep(100);
                System.out.println(name +"售出一张票,剩余:"+ (-- ticketNum) +"张票..");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //2.使用同步代码块：锁为同一其他对象
    public void sell2(){
        synchronized (lock){
            if(ticketNum <= 0){
                System.out.println("没票了,停止售票...");
                ifLoop = false;
                return;
            }
            String name = Thread.currentThread().getName();
            try {
                Thread.sleep(100);
                System.out.println(name +"售出一张票,剩余:"+ (-- ticketNum) +"张票..");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //3.同步方法：锁为this
    public synchronized void sell3(){
        if(ticketNum <= 0){
            System.out.println("没票了,停止售票...");
            ifLoop = false;
            return;
        }
        String name = Thread.currentThread().getName();
        try {
            Thread.sleep(100);
            System.out.println(name +"售出一张票,剩余:"+ (-- ticketNum) +"张票..");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //4.静态同步方法：锁为类名.class 即：SellTicketSafe.class
    public static synchronized void sell4(){
        if(ticketNum <= 0){
            System.out.println("没票了,停止售票...");
            ifLoop = false;
            return;
        }
        String name = Thread.currentThread().getName();
        try {
            Thread.sleep(100);
            System.out.println(name +"售出一张票,剩余:"+ (-- ticketNum) +"张票..");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //5.静态同步方法：锁为类名.class 即：SellTicketSafe.class
    public static void sell5(){
        synchronized(SellTicketSafe.class){
            if(ticketNum <= 0){
                System.out.println("没票了,停止售票...");
                ifLoop = false;
                return;
            }
            String name = Thread.currentThread().getName();
            try {
                Thread.sleep(100);
                System.out.println(name +"售出一张票,剩余:"+ (-- ticketNum) +"张票..");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}